package com.zhu.tool_test.starke.util.weapons;



import com.zhu.tool_test.starke.matrix.multipart.core.MultipartData;

import java.util.ArrayList;
import java.util.List;

/**
 * @author 4everlynn
 * @version V1.0
 * @description
 * @date 2019-08-29
 */
public abstract class BaseTreeStructureAdapter<T> {

    /**
     * children label
     *
     * @return children label
     */
    public abstract String childrenNodeName();

    /**
     * function to get root node
     *
     * @return root node
     */
    public abstract List<T> root();

    /**
     * function to get children node
     *
     * @param data data
     * @return children node
     */
    public abstract List<T> getChildren(T data);

    private List<MultipartData> buildTree(List<T> dataList) {
        List<MultipartData> result = new ArrayList<>();
        for (T data : dataList) {
            this.build(data, result);
        }
        return result;
    }

    /**
     * hook when build end
     *
     * @param leaf leaf
     */
    protected void onLeafBuildEnd(T leaf) {}

    protected void onParentInject(MultipartData parent) {
    }

    /**
     * generate tree structure
     *
     * @return tree structure
     */
    public List<MultipartData> generate() {
        return this.buildTree(this.root());
    }

    private void build(T data, List<MultipartData> collection) {
        MultipartData temporary = new MultipartData();
        temporary.parties(data);
        // hook
        this.onParentInject(temporary);
        List<T> children = this.getChildren(data);
        List<MultipartData> childrenNode
                = temporary.includeAndReturn(this.childrenNodeName(), new ArrayList<>());
        if (children.size() > 0) {
            for (T child : children) {
                this.build(child, childrenNode);
            }
        } else {
            this.onLeafBuildEnd(data);
        }
        temporary.include(this.childrenNodeName(), childrenNode);
        collection.add(temporary);
    }
}
